% !TeX encoding=utf8
% !TeX spellcheck = en-US

\chapter{Customs}
\label{chap:Customs}

Customs refer to Qt objects that you can add to the GUI without changing the main application. There are CustomContextMenuItems (\ref{sec:CustomContextMenuItem}) and CustomTabs (\ref{sec:CustomTab}). CustomContextMenuItems allow you add menu items to the right click menu on shapes. It is possible to open input dialogs to get certin parameters for the function but if you need more complex inputs or outputs you are better off with a CustomTab. To make your Customs visible in the GUI you have to register them (see \ref{sec:RegisterCustoms}).

\section{CustomContextMenuItem}
\label{sec:CustomContextMenuItem}

\begin{itemize}
	\item \textbf{Have to implement} CustomContextMenuItem
	\item \textbf{Found in} custom/contextMenuItems
	\item \textbf{Use when} your algorithm works with exactly one shape and has limited input parameters
	\item\textbf{Naming convention} <MeaningfulName>ContextMenuItem
\end{itemize}

The abstract CustomContextMenuItem class is very limited and there is only one function to implement. See \ref{subsec:ExampleVoronoiCellsContextMenuItem} for an example. 

\subsection{Abstract Functions}

\begin{itemize}
	\item \textbf{\texttt{onClick(vtkIdType pointId, vtkIdType faceId, QWidget* parent)}} Is triggered when the menu item was clicked. 
	\begin{itemize}
		\item \texttt{pointId} refers to the id of the closest vertex of the shape in the vtkPolyData of the shape to where the click was. 
		\item \texttt{faceId} refers to the id of the face of the shape in the vtkPolyData of the shape under the click. 
		\item \texttt{parent} is a reference to the ShapeAnalyzer Widget which is needed to open QInputDialogs.
	\end{itemize}
\end{itemize}

\subsection{Class attributes}
\begin{itemize}
	\item \texttt{shared\_ptr<Shape>} \textbf{\texttt{shape\_}} Reference to the clicked shape
	\item \texttt{ShapeAnalyzerInterface*} \textbf{\texttt{shapeAnalyzer\_}} Reference to the ShapeAnalyzerInterface, see \ref{sec:ShapeAnalyzerInterface}
\end{itemize}

\subsection{Example: VoronoiCellsContextMenuItem}
\label{subsec:ExampleVoronoiCellsContextMenuItem}

\begin{lstlisting}[style=lstStyleCpp, caption={VoronoiCellsContextMenuItem.h}]
template<class T = Metric>
class VoronoiCellsContextMenuItem : public CustomContextMenuItem {
public:
    VoronoiCellsContextMenuItem<T>(
         shared_ptr<Shape> shape, 
         ShapeAnalyzerInterface* shapeAnalyzer) 
    : CustomContextMenuItem(shape, shapeAnalyzer) {}
    
    virtual void onClick(vtkIdType pointId, vtkIdType faceId, QWidget* parent) {
        bool ok;
        vtkIdType source = QInputDialog::getInt(
                         parent,
                         "Source vertex",
                         "Choose ID of source vertex.",
                         0, 0,
                         shape_->getPolyData()->GetNumberOfPoints()-1,
                         1, &ok);
        if (!ok) {
            return;
        }
        vtkIdType numberOfSegments = QInputDialog::getInt(
                           parent,
                           "Number of segments",
                           "Choose number of segments",
                           0, 0,
                           shape_->getPolyData()->GetNumberOfPoints()-1,
                           1, &ok);
        if(ok) {
            try {
                auto m = make_shared<T>(shape_);
                auto fps = make_shared<FarthestPointSampling>(
                                   shape_, m, source, numberOfSegments);
                VoronoiCellSegmentation segmentation(shape_, m, fps);
                
                // save current segmentation for being able to create 
                // new shapes out of the segments
                shared_ptr<Shape::Coloring> coloring 
                             = make_shared<Shape::Coloring>();
                coloring->type = Shape::Coloring::Type::PointSegmentation;
                coloring->values = segmentation.getSegments();
                shape_->setColoring(coloring);
            } catch(metric::MetricError& e) {
                QMessageBox::warning(parent, "Exception", e.what());
            }
        }
    }
};

\end{lstlisting}

In \texttt{line 2} we of course inherit from CustomContextMenuItem. 

The constructor (\texttt{line 4 to 7}) is mandatory like this (not really, for more information look up \ref{sec:RegisterCustoms}). Every normal CustomContextMenuItem should be constructed with those two parameters and should call the super constructor. 

The \texttt{onClick} function (\texttt{line 9 to 48}) is the important one. There are two QInputDialogs that get the source point and the number of segments. There are 4 different types of \href{http://qt-project.org/doc/qt-4.8/qinputdialog.html}{QInputDialogs} (see the static public member functions for details) that restrict the type of inputs you can get for your functions via context menu items. It is important to use the \texttt{parent} input as the parent widget here. 
Then you can call any code you want using the Shape and the ShapeAnalyzerInterface as well as the results from the dialogs as inputs. Notice that all the objects we constructed here (except the Coloring) will be destroyed afterwards. If you want to reuse a computationally intense object later in an algorithm, use a CustomTab instead.
The Metric object might throw MetricError which is catched here. All error messages should be created on this level (see \ref{sec:Errors}).

This class is special because it is a template. The template parameter is the Metric that should be used for calculating the Voronoi cells. If you have a template menu item you have to register every possible parameter individually for them to appear in the GUI (\ref{sec:RegisterCustoms}). 

\section{CustomTab}
\label{sec:CustomTab}

\begin{itemize}
	\item \textbf{Have to implement} CustomTab
	\item \textbf{Found in} custom/tabs
	\item \textbf{Use when} your algorithm is too complex for a menu item or when you might want to store information
	\item \textbf{Naming convention} <MeaningfulName>Tab
\end{itemize}

CustomTabs can be loaded into the menu on the right side of the ShapeAnalyzer. Every CustomTab is its own QWidget and can be freely designed (but maybe think about the space restrictions in the menu) in the QtCreator (or by hand if you like that). 

\begin{mdframed}
	The actual use of the abstract functions is to keep your GUI updated about which objects (mainly shapes) exist. This is not done automatically, but you can find a pattern in the example (\ref{subsec:ExampleIdentityMatchingTab}). Of course you only need to do that if you have a list of shapes or something similar in your tab.
\end{mdframed}

\subsection{Abstract Functions}

\begin{itemize}
	\item \textbf{\texttt{onShapeAdd(Shape* shape)}} Is triggered when a new shape was added to the ShapeAnalyzer. 
	\begin{itemize}
		\item \texttt{shape} Reference to Shape that was added. 
	\end{itemize}
\end{itemize}

\begin{itemize}
	\item \textbf{\texttt{onShapeEdit(Shape* shape)}} Is triggered when an attribute of a shape was changed (for example the name).
	\begin{itemize}
		\item \texttt{shape} Reference to Shape that was edited. 
	\end{itemize}
\end{itemize}

\begin{itemize}
	\item \textbf{\texttt{onShapeDelete(Shape* shape)}} Is triggered when a shape was deleted.
	\begin{itemize}
		\item \texttt{shape} Reference to Shape that was deleted. 
	\end{itemize}
\end{itemize}

\begin{itemize}
	\item \textbf{\texttt{onClear()}} Is triggered when the GUI is cleared, this means all shapes and correspondences will be deleted.
\end{itemize}

\subsection{Class attributes}
\begin{itemize}
	\item \texttt{const HashMap<vtkActor*, shared\_ptr<Shape>>\&} \textbf{\texttt{shapes\_}} Read-only reference to all shapes
	\item \texttt{const HashMap<shared\_ptr<PointCorrespondence>, bool>\&} \textbf{\texttt{pointCorrespondences\_}} Read-only reference to all point correspondences
	\item \texttt{const HashMap<shared\_ptr<FaceCorrespondence>, bool>\&} \textbf{\texttt{faceCorrespondences\_}} Read-only reference to all face correspondences
	\item \texttt{ShapeAnalyzerInterface*} \textbf{\texttt{shapeAnalyzer\_}} Reference to the ShapeAnalyzerInterface, see \ref{sec:ShapeAnalyzerInterface}
\end{itemize}

\subsection{Qt User Interface}
\label{subsec:QtUI}

You probably want to create the layout for your tab with the QtCreator. Put your .ui file in the custom/tabs folder and name it correspondingly to your tab: <MeaningfulName>TabWidget.ui. During the creation make sure that you named the Widget accordinglly, too. If you didn't do that or you are not sure, the beginning of the .ui should look like this: 

\begin{lstlisting}[style=lstStyleCpp, caption={IdentityMatchingTabWidget.ui}]
...
<class>IdentityMatchingTabWidget</class>
<widget class="QWidget" name="IdentityMatchingTabWidget">
...
\end{lstlisting}

Then you can inherit from UI::<YourUIClassName> and your widget will be layouted appropriately. You have to include ui\_<YourUIClassName>.h for the class to be found. This file will be automatically created so don't worry if you can't find it before compiling. 


\subsection{Example: IdentityMatchingTab}
\label{subsec:ExampleIdentityMatchingTab}

\begin{lstlisting}[style=lstStyleCpp, caption={IdentityMatchingTab.h}]
#include "ui_IdentityMatchingTabWidget.h"

class IdentityMatchingTab : 
                            public QWidget, 
                            private Ui::IdentityMatchingTabWidget, 
                            public CustomTab 
{
    Q_OBJECT
    
public:
    IdentityMatchingTab(
      const HashMap<vtkActor*, shared_ptr<Shape>>& shapes,
      const HashMap<shared_ptr<PointCorrespondence>, bool>& pointCorrespondences,
      const HashMap<shared_ptr<FaceCorrespondence>, bool>& faceCorrespondences,
      ShapeAnalyzerInterface* shapeAnalyzer);
    
    virtual ~IdentityMatchingTab();
    
    virtual void onShapeDelete(Shape* shape);
    virtual void onShapeAdd(Shape* shape);
    virtual void onShapeEdit(Shape* shape);
    virtual void onClear();
private slots:
    virtual void slotMatch();
    virtual void slotToggleMode();
};
\end{lstlisting}

Every CustomTab implementation has to inherit from \texttt{QWidget} and \texttt{CustomTab}. Additionally, if you created a .ui file for the layout, it has to inherit from \texttt{Ui::<YourUIClassName>}. See \ref{subsec:QtUI} for more details about that.

Put the \texttt{Q\_OBJECT} keyword as in \texttt{line 8} if your widget is interactive i.e. you want to send signals for example from buttons. 

Different from the context menu items, the constructor has to be implemented to setup the widget as well as all abstract functions. For those who have no experience with Qt take a look at the .cpp files for some impressions especially of the signal and slot system.

\begin{lstlisting}[style=lstStyleCpp, caption={IdentityMatchingTab.cpp, Constructor}]
custom::tabs::IdentityMatchingTab::IdentityMatchingTab(...)
        :   QWidget(dynamic_cast<QWidget*>(shapeAnalyzer), 0),
            CustomTab(...)
{
    this->setupUi(this);
    
    QStringList labels  = getShapeIdentifierList();
    
    if(shapes_.size() < 2) {
        buttonMatch->setEnabled(false);
    }
    
    comboBoxShape1->insertItems(0, labels);
    comboBoxShape2->insertItems(0, labels);
    
    connect(this->buttonMatch,    SIGNAL(released()),
                  this,    SLOT(slotMatch()));
    connect(this->buttonGroupMatch, SIGNAL(buttonClicked(int)),
                  this,    SLOT(slotToggleMode()));
}
\end{lstlisting}

In the constructor you have to set up the widget and connect all signals and slots (\href{http://qt-project.org/doc/qt-4.8/signalsandslots.html}{Signals \& Slots}) as well as other variable output, here two combo boxes that contain lists of all shapes. 

In several GUI elements only a string (a QString actually) is stored and then we need to get the right shape using only this string when interaction with this element takes place. The identifier string looks like this: <shapeId>:<shapeName>. Because this is tedious work, the CustomTab class has functions to deal with that: 

\begin{itemize}
	\item \textbf{\texttt{QString getShapeIdentifier(Shape*)}} returns the identifier in the right form
	\item \textbf{\texttt{vtkIdType getIdFromIdentifier(QString)}} returns the id from a valid identifier
	\item \textbf{\texttt{shared\_ptr<Shape> getShapeFromId(vtkIdType)}} returns the shape from an id
	\item \textbf{\texttt{QStringList getShapeIdentifierList()}} returns a QStringList with all shape identifiers
	\item \textbf{\texttt{shared\_ptr<Shape> getShapeFromIdentifier(QString)}} returns shape from an identfier
\end{itemize}

In the example we get all shape identifiers (\texttt{line 7}) and fill both combo boxes with them (\texttt{line 13 + 14}). The combo boxes are not updated automatically though, that's what done in the abstract functions. 

\begin{mdframed}
\textbf{But why don't we use just the names for the shape identifier?} Because it is possible that two shapes have the same name and then they can't be distinguished. The id is unique but it's not userfriendly.
\end{mdframed}

\begin{lstlisting}[style=lstStyleCpp, caption={IdentityMatchingTab.cpp, onShapeAdd}]
void custom::tabs::IdentityMatchingTab::onShapeAdd(Shape* shape) {
    QString label = getShapeIdentifier(shape);
    comboBoxShape1->insertItem(0, label);
    comboBoxShape2->insertItem(0, label);
    
    if(shapes_.size() >= 2) {
        this->buttonMatch->setEnabled(true);
    }
}
\end{lstlisting}

This function is called everytime a shape is added to the main application and this tab was added to the menu before. It creates an identifier for the new shape and adds it both combo boxes. Additionally, the match button is activated if more than two shapes exist. The source code of the other abstract functions is not listed here, but you can basically just go and copy it if you update shape lists. 

\section{Registering Customs}
\label{sec:RegisterCustoms}

Besides from implementing a concrete menu item or tab, the custom has to be registered in order to be shown in the GUI. This can be done in the class \texttt{CustomClassesRegistry} in the folder \texttt{custom}. There is a standard way to do it explained below but if it does not suffice for your purpose take a look at the Factory section (\ref{sec:Factory}).

\subsection{Register a CustomContextMenuItem}
\label{subsec:RegisterMenuItem}

In \texttt{CustomClassesRegistry.h} add your menu item to the \texttt{registerContextMenuItems()} function. Your registration must have the form 

\texttt{CustomContextMenuItemFactory::getInstance()->Register< <NameOfYourClass> > \linebreak
	\hspace*{2ex}(<UniqueStringIdentifier>, <LabelPath>)}
	
where \texttt{<NameOfYourClass>} is the specific class you want to create, for example ColorMetricContextMenuItem<GeodesicMetric>. \texttt{<UniqueStringIdentifier>} is a string that should be meaningful and not identical to any other string in the registry list. \texttt{<LabelPath>} is a string that describes how the menu item should be labeled as well as its path, for example \texttt{"Coloring>>Metric>>Geodesic"} will produce a 3-layered menu (see Figure \ref{fig:MenuPath} for an example). If several menu items have the same path (up to some layer), these will of course be merged.

\subsection{Register a CustomTab}
\label{subsec:RegisterTab}

In \texttt{CustomClassesRegistry.h} add your menu item to the \texttt{registerTabs()} function. Your registration must have the form
 
\texttt{CustomTabFactory::getInstance()->Register< <NameOfYourClass> > \linebreak
	\hspace*{2ex}(<UniqueStringIdentifier>, <LabelPath>)}

where \texttt{<NameOfYourClass>} is the specific class you want to create, for example CorrespondenceColoringTab. \texttt{<UniqueStringIdentifier>} is a string that should be meaningful and not identical to any other string in the registry list. \texttt{<LabelPath>} is a string that describes the label of the tab and whether it is a correspondence or shape tab, for example \texttt{"Correspondences>>Correspondence Coloring"} or \texttt{"Shapes>>Mesh Checker"}. Different from menu items not arbitrary many layers are possible and only Shapes and Correspondences are possible groups. The groups just loosely describe whether the tab deals more with shapes or more with correspondences.